package com.qdlc.p2p.biz.service.impl;

import java.io.File;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.qdlc.p2p.biz.borrowworker.BorrowHelper;
import com.qdlc.p2p.biz.borrowworker.worker.BorrowWorker;
import com.qdlc.p2p.biz.executer.AbstractExecuter;
import com.qdlc.p2p.biz.executer.ExecuterHelper;
import com.qdlc.p2p.biz.executer.impl.BorrowVerifyFailNoticeExecuter;
import com.qdlc.p2p.biz.executer.impl.BorrowVerifySuccNoticeExecuter;
import com.qdlc.p2p.biz.executer.impl.ExperienceVerifyExecuter;
import com.qdlc.p2p.biz.processor.event.BorrowValueEvent;
import com.qdlc.p2p.biz.processor.task.VerifyFullSuccessTaskProcessor;
import com.qdlc.p2p.biz.service.AutoBorrowService;
import com.qdlc.p2p.biz.service.BorrowService;
import com.qdlc.p2p.biz.service.TppInvestService;
import com.qdlc.p2p.biz.task.ConcurrentUtil;
import com.qdlc.p2p.biz.util.IdcardUtils;
import com.qdlc.p2p.common.constant.BorrowCategory;
import com.qdlc.p2p.common.constant.BorrowRepaymentStatus;
import com.qdlc.p2p.common.constant.BorrowScales;
import com.qdlc.p2p.common.constant.BorrowStatus;
import com.qdlc.p2p.common.constant.BorrowStyle;
import com.qdlc.p2p.common.constant.BorrowTenderStatus;
import com.qdlc.p2p.common.constant.BorrowTimeType;
import com.qdlc.p2p.common.constant.BorrowType;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.constant.ManageFeeCalStyle;
import com.qdlc.p2p.common.constant.SinaConstant;
import com.qdlc.p2p.common.constant.VerifyLogType;
import com.qdlc.p2p.common.constant.VerifyType;
import com.qdlc.p2p.common.core.queue.QueueHandlers;
import com.qdlc.p2p.common.exception.BorrowException;
import com.qdlc.p2p.common.exception.BusinessException;
import com.qdlc.p2p.common.util.BeanUtil;
import com.qdlc.p2p.common.util.BigDecimalUtil;
import com.qdlc.p2p.common.util.CollectionUtils;
import com.qdlc.p2p.common.util.DataUtils;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.OrderNoUtil;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.dal.checkrule.AutoTenderConfRuleCheck;
import com.qdlc.p2p.dal.checkrule.BorrowManageFeeRuleCheck;
import com.qdlc.p2p.dal.common.RuleCheckHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper.Nid;
import com.qdlc.p2p.dal.common.model.jpa.OrderFilter.OrderType;
import com.qdlc.p2p.dal.common.model.jpa.PageDataList;
import com.qdlc.p2p.dal.common.model.jpa.QueryParam;
import com.qdlc.p2p.dal.common.model.jpa.SearchFilter;
import com.qdlc.p2p.dal.common.model.jpa.SearchFilter.Operators;
import com.qdlc.p2p.dal.dao.AccountDao;
import com.qdlc.p2p.dal.dao.BondCollectionDao;
import com.qdlc.p2p.dal.dao.BorrowCollectionDao;
import com.qdlc.p2p.dal.dao.BorrowConfigDao;
import com.qdlc.p2p.dal.dao.BorrowDao;
import com.qdlc.p2p.dal.dao.BorrowMortgageDao;
import com.qdlc.p2p.dal.dao.BorrowRepaymentDao;
import com.qdlc.p2p.dal.dao.BorrowTenderDao;
import com.qdlc.p2p.dal.dao.BorrowUploadDao;
import com.qdlc.p2p.dal.dao.UpRateCollectionDao;
import com.qdlc.p2p.dal.dao.UserBaseInfoDao;
import com.qdlc.p2p.dal.dao.UserCreditDao;
import com.qdlc.p2p.dal.dao.UserCreditLogDao;
import com.qdlc.p2p.dal.dao.UserVipUprateCollectionDao;
import com.qdlc.p2p.dal.dao.VerifyLogDao;
import com.qdlc.p2p.dal.dto.Account;
import com.qdlc.p2p.dal.dto.BondCollection;
import com.qdlc.p2p.dal.dto.Borrow;
import com.qdlc.p2p.dal.dto.BorrowCollection;
import com.qdlc.p2p.dal.dto.BorrowConfig;
import com.qdlc.p2p.dal.dto.BorrowMortgage;
import com.qdlc.p2p.dal.dto.BorrowRepayment;
import com.qdlc.p2p.dal.dto.BorrowTender;
import com.qdlc.p2p.dal.dto.BorrowUpload;
import com.qdlc.p2p.dal.dto.Operator;
import com.qdlc.p2p.dal.dto.TppTradeLog;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.dto.UserCredit;
import com.qdlc.p2p.dal.dto.UserCreditLog;
import com.qdlc.p2p.dal.dto.VerifyLog;
import com.qdlc.p2p.dal.model.BorrowModel;
import com.qdlc.p2p.dal.model.BorrowRepaymentModel;
import com.qdlc.p2p.dal.util.UserUtils;

@Service("borrowService")
public class BorrowServiceImpl implements BorrowService {

	public final static Logger logger = Logger.getLogger(BorrowServiceImpl.class);

	@Resource
	private AutoBorrowService autoBorrowService;

	@Resource
	private TppInvestService tppInvestService;

	@Resource
	private UserCreditDao userCreditDao;

	@Resource
	private UserBaseInfoDao userInfoDao;

	@Resource
	private UserCreditLogDao userCreditLogDao;

	@Resource
	private BorrowDao borrowDao;

	@Resource
	private BorrowConfigDao borrowConfigDao;

	@Resource
	private AccountDao accountDao;

	@Resource
	private BorrowRepaymentDao borrowRepaymentDao;

	@Resource
	private BorrowTenderDao borrowTenderDao;

	@Resource
	private BorrowUploadDao borrowUploadDao;

	@Resource
	private VerifyLogDao verifyLogDao;

	@Resource
	private BorrowMortgageDao borrowMortgageDao;

	@Resource
	private BorrowCollectionDao borrowCollectionDao;

	@Resource
	private UserVipUprateCollectionDao userVipUprateCollectionDao;

	@Resource
	private UpRateCollectionDao upRateCollectionDao;

	@Resource
	private BondCollectionDao bondCollectionDao;

	@Override
	public Borrow save(BorrowModel model, User user, List<BorrowUpload> list) {
		Borrow borrow = model.prototype();
		BorrowWorker worker = BorrowHelper.getWorker(borrow);
//		String bid_no = DateUtil.dateStr3(DateUtil.getNow()).substring(2);
//		borrow.setBidNo(bid_no);
//		borrow.setDealNo(bid_no);
		// 发标，创建每个借款标的uuid，保证每一个uuid为唯一
		String uuid = OrderNoUtil.getInstance().getSerialNumber();
		borrow.setBidNo(uuid);
		borrow.setDealNo(uuid);
		borrow.setUuid(uuid);
		borrow.setManageFee(borrow.getManageFee());
		worker.checkModelData();
		// 认证校验，信用标额度校验
		worker.allowPublish(user);
		worker.setBorrowField(user);
		Borrow addBorrow = borrowDao.save(borrow);
		List<BorrowUpload> l = new ArrayList<BorrowUpload>();
		for (BorrowUpload bu : list) {
			bu.setBorrow(borrow);
			l.add(bu);
		}
		borrowUploadDao.save(l);
		// 秒标需要发标时就冻结资金(自动审核初审)
		if (worker.getBorrowConfig().isTrail()) {
			borrow = worker.handleBorrowBeforePublish(borrow);
			// 是否跳过初审
			worker.skipTrial(addBorrow);
		}
		// 信用标或学信标
		worker.handleBorrowAfterPublish(addBorrow);

		// 发送通知
		/*
		 * Global.setTransfer("user", user);
		 * Global.setTransfer("borrow", addBorrow);
		 * AbstractExecuter executer = ExecuterHelper.doExecuter("publishBorrowNoticeExecuter");
		 * executer.execute(0, user);
		 */
		return addBorrow;
	}

	@Override
	public void update(Borrow borrow) {
		BorrowWorker worker = BorrowHelper.getWorker(borrow);
		worker.handleBorrowAfterPublish(borrow);
		borrowDao.update(borrow);
	}

	@Override
	public PageDataList<BorrowModel> list(BorrowModel model) {
		QueryParam param = QueryParam.getInstance();
		if (model != null) {
			if (StringUtil.isNotBlank(model.getSearchName())) {
				SearchFilter filter1 = new SearchFilter("name", Operators.LIKE, model.getSearchName().trim());
				SearchFilter filter2 = new SearchFilter("user.userName", Operators.LIKE, model.getSearchName().trim());
				param.addOrFilter(filter1, filter2);
			}
			if ((model.getUser() != null) && (model.getUser().getUserId() > 0)) {
				param.addParam("user.userId", model.getUser().getUserId());
			}
			if (model.getStatus() != 99) {
				switch (model.getStatus()) {
				case 1:
					param.addParam("status", 1);
					if (model.getScales() == 100) {
						param.addParam("accountYes", Operators.PROPERTY_EQ, "account");
					} else {
						param.addParam("accountYes", Operators.PROPERTY_NOTEQ, "account");
					}
					break;
				case 19:
					param.addParam("status", 1);
					param.addParam("accountYes", Operators.PROPERTY_EQ, "account");
					break;
				case 49:
					SearchFilter orFilter1 = new SearchFilter("status", Operators.EQ, 4);
					SearchFilter orFilter2 = new SearchFilter("status", Operators.EQ, 49);
					param.addOrFilter(orFilter1, orFilter2);
					break;
				case 59:
					SearchFilter orFilter3 = new SearchFilter("status", Operators.EQ, 5);
					SearchFilter orFilter4 = new SearchFilter("status", Operators.EQ, 59);
					param.addOrFilter(orFilter3, orFilter4);
					break;
				default:
					param.addParam("status", model.getStatus());
					break;
				}
			}
			if (model.getScales() == 99) {
				param.addParam("account", Operators.PROPERTY_GT, "accountYes");
				// param.addParam("type", Operators.NOTEQ, 110); 删除对流转标的限制
			}
			if (StringUtil.isNotBlank(model.getUserName())) {
				param.addParam("user.userName", Operators.LIKE, model.getUserName().trim());
			}
			Date d = DateUtil.getDate((System.currentTimeMillis() / 1000) + "");
			if (model.getTime() == 7) {
				param.addParam("addTime", Operators.GTE, DateUtil.rollDay(d, -7));
				param.addParam("addTime", Operators.LTE, d);
			} else if ((model.getTime() > 0) && (model.getTime() < 4)) {
				param.addParam("addTime", Operators.GTE, DateUtil.rollMon(d, -model.getTime()));
				param.addParam("addTime", Operators.LTE, d);
			}
			if (StringUtil.isNotBlank(model.getStartTime())) {
				Date start = DateUtil.valueOf(model.getStartTime() + " 00:00:00");
				param.addParam("addTime", Operators.GT, start);
			}
			if (StringUtil.isNotBlank(model.getEndTime())) {
				Date end = DateUtil.valueOf(model.getEndTime() + " 23:59:59");
				param.addParam("addTime", Operators.LTE, end);
			}
			if ((model.getType() != 100) && (model.getType() != 0)) {
				param.addParam("type", model.getType());
			}
			searchParam(param, model);
			param.addPage(model.getPage(), model.getRows());
		}
		PageDataList<Borrow> pageDataList = borrowDao.findPageList(param);
		PageDataList<BorrowModel> pageDataList_ = new PageDataList<BorrowModel>();
		List<BorrowModel> list = new ArrayList<BorrowModel>();
		pageDataList_.setPage(pageDataList.getPage());
		VerifyLogDao verifyLogDao = (VerifyLogDao) BeanUtil.getBean("verifyLogDao");

		if (pageDataList.getList().size() > 0) {
			for (int i = 0; i < pageDataList.getList().size(); i++) {
				Borrow borrow = pageDataList.getList().get(i);
				BorrowModel bm = BorrowModel.instance(borrow);
				if (borrow.getUser() != null) {
					bm.setUserName(borrow.getUser().getUserName());
					bm.setUserId(borrow.getUser().getUserId());
				} else {
					bm.setUserName("<font color='red'>该用户被删除</font>");
					bm.setUserId(0);
				}
				if ((borrow.getRegisterTime() != null) && (DateUtil
						.getNowTime() > (DateUtil.rollMinute(borrow.getRegisterTime(), 35).getTime() / 1000))) {
					bm.setIsShowRegister(1);
				}
				VerifyLog log = verifyLogDao.findByType(borrow.getId(), "borrow", 1);
				if (log != null) {
					/*
					 * Date d = log.getTime(); //初审时间
					 * Calendar c = Calendar.getInstance();
					 * c.setTime(d);
					 * c.add(Calendar.DATE, borrow.getValidTime());
					 * Calendar now = Calendar.getInstance();
					 * now.setTime(DateUtil.getNow());
					 */
					bm.setStartTime(DateUtil.dateStr2(log.getTime()));
				}
				bm.setUser(null);
				list.add(bm);
			}
		}
		pageDataList_.setList(list);
		return pageDataList_;
	}

	/* (non-Javadoc)
	 * @see com.qdlc.p2p.biz.service.BorrowService#manageList(com.qdlc.p2p.dal.model.BorrowModel)
	 */
	@Override
	public PageDataList<BorrowModel> manageList(BorrowModel model) {
		QueryParam param = QueryParam.getInstance();
		if (model != null) {// 模糊查询
		    String searchName = StringUtil.isNull(model.getSearchName());
			if (!StringUtil.isBlank(searchName)) {// 模糊查询条件
				SearchFilter orFilter1 = new SearchFilter("user.userName", Operators.LIKE,
				        searchName);
				SearchFilter orFilter2 = new SearchFilter("user.realName", Operators.LIKE,
				        searchName);
				SearchFilter orFilter3 = new SearchFilter("name", Operators.LIKE, searchName);
				param.addOrFilter(orFilter1, orFilter2, orFilter3);
			} else { // 精确查询条件
			    String userName = StringUtil.isNull(model.getUserName());
				if (StringUtil.isNotBlank(userName)) {
					param.addParam("user.userName", Operators.LIKE, userName);
				}
				String realName = StringUtil.isNull(model.getRealName());
				if (StringUtil.isNotBlank(realName)) {
					param.addParam("user.realName", Operators.LIKE, realName);
				}
				String name = StringUtil.isNull(model.getName());
				if(StringUtil.isNotBlank(name)){
					param.addParam("name", Operators.LIKE, name);
				}
				if (StringUtil.isNotBlank(model.getStartTime())) {
					Date start = DateUtil.valueOf(model.getStartTime() + " 00:00:00");
					param.addParam("addTime", Operators.GT, start);
				}
				if (StringUtil.isNotBlank(model.getEndTime())) {
					Date end = DateUtil.valueOf(model.getEndTime() + " 23:59:59");
					param.addParam("addTime", Operators.LTE, end);
				}
				if ((model.getType() != 100)
				        && (model.getType() != 0)) { // 标种是从101开始的
					param.addParam("type", model.getType());
				}
		    }
			
            if (model.getStatus() != BorrowStatus.STATUS_UNKNOWN) {
                param.addParam("status", model.getStatus());
            }
            if (model.getScales() == BorrowScales.HUNDRED_PERCENT) {
                param.addParam("accountYes", Operators.PROPERTY_EQ, "account");
            }
            param.addOrder(OrderType.DESC, "id");
            param.addPage(model.getPage(), model.getRows());
        }
		
		PageDataList<Borrow> pageDataList = borrowDao.findPageList(param);
		PageDataList<BorrowModel> pageDataList_ = new PageDataList<BorrowModel>();
		List<BorrowModel> list = new ArrayList<BorrowModel>();
		pageDataList_.setPage(pageDataList.getPage());
		
		VerifyLogDao verifyLogDao = (VerifyLogDao) BeanUtil.getBean("verifyLogDao");

		if (CollectionUtils.isNotNullOrEmpty(pageDataList.getList())) {
		    for (Borrow borrow : pageDataList.getList()) {
		        BorrowModel bm = BorrowModel.instance(borrow);
                if (borrow.getUser() != null) {
                    bm.setUserName(borrow.getUser().getUserName());
                    bm.setRealName(borrow.getUser().getRealName());
                    bm.setUserId(borrow.getUser().getUserId());
                } else {
                    bm.setUserName("<font color='red'>该用户被删除</font>");
                    bm.setUserId(0);
                }
                if ((borrow.getRegisterTime() != null) 
                        && (DateUtil.getNowTime() > (DateUtil.rollMinute(borrow.getRegisterTime(), 35).getTime() / 1000))) {
                    bm.setIsShowRegister(1);
                }
                VerifyLog log = verifyLogDao.findByType(borrow.getId(), VerifyLogType.BORROW, VerifyType.TRIAL);
                if (log != null) {
                    bm.setStartTime(DateUtil.dateStr2(log.getTime()));
                }
                bm.setUser(null);
                list.add(bm);
            }
		}
		pageDataList_.setList(list);
		return pageDataList_;
	}

	/**
	 * 前台分页
	 * 
	 * @param model
	 * @return
	 */
	@Override
	public PageDataList<BorrowModel> getList(BorrowModel model) {
		PageDataList<Borrow> pageDataList = borrowDao.getList(model);
		PageDataList<BorrowModel> pageDataList_ = new PageDataList<BorrowModel>();
		List<BorrowModel> list = new ArrayList<BorrowModel>();
		pageDataList_.setPage(pageDataList.getPage());
		VerifyLogDao verifyLogDao = (VerifyLogDao) BeanUtil.getBean("verifyLogDao");

		if (pageDataList.getList().size() > 0) {
			for (int i = 0; i < pageDataList.getList().size(); i++) {
				Borrow borrow = pageDataList.getList().get(i);
				BorrowModel bm = BorrowModel.instance(borrow);
				try {
					if (model.getScales() != 101) {
						bm.setUserName(borrow.getUser().getUserName());
						bm.setRealName(borrow.getUser().getRealName());
						bm.setUserId(borrow.getUser().getUserId());
					}
				} catch (Exception e) {
					bm.setUserName("<font color='red'>该用户被删除</font>");
					bm.setUserId(0);
				}

				VerifyLog log = verifyLogDao.findByType(borrow.getId(), "borrow", 1);
				if (log != null) {
					/*
					 * Date d = log.getTime(); //初审时间
					 * Calendar c = Calendar.getInstance();
					 * c.setTime(d);
					 * c.add(Calendar.DATE, borrow.getValidTime());
					 * Calendar now = Calendar.getInstance();
					 * now.setTime(DateUtil.getNow());
					 * bm.setFlow(c.before(now));
					 */
					bm.setStartTime(DateUtil.dateStr4(log.getTime()));
				}
				bm.setBorrowId(borrow.getId());
				bm.setUser(null);
				bm.setIps(model.getIps());
				bm.setCategory(borrow.getCategory());
				bm.setInvestCount(borrow.getInvestCount());
				list.add(bm);
			}
		}
		pageDataList_.setList(list);
		return pageDataList_;
	}

	/**
	 * 首页显示标
	 *
	 * @param model
	 * @return
	 */
	@Override
	public PageDataList<BorrowModel> getBorrowListForIndex(BorrowModel model) {
		PageDataList<Borrow> pageDataList;
		if (model.getCategorys()[0] == 2) {
			pageDataList = borrowDao.getBorrowListForIndexExp(model);
			if (pageDataList.getList().size() <=0) {
				pageDataList = borrowDao.getLastBorrowForIndexExp(model);
			}
		} else {
			pageDataList = borrowDao.getBorrowListForIndex(model);
		}
		PageDataList<BorrowModel> pageDataList_ = new PageDataList<BorrowModel>();
		List<BorrowModel> list = new ArrayList<BorrowModel>();
		pageDataList_.setPage(pageDataList.getPage());
		VerifyLogDao verifyLogDao = (VerifyLogDao) BeanUtil.getBean("verifyLogDao");

		if (pageDataList.getList().size() > 0) {
			for (int i = 0; i < pageDataList.getList().size(); i++) {
				Borrow borrow = pageDataList.getList().get(i);
				BorrowModel bm = BorrowModel.instance(borrow);
				try {
					if (model.getScales() != 101) {
						bm.setUserName(borrow.getUser().getUserName());
						bm.setRealName(borrow.getUser().getRealName());
						bm.setUserId(borrow.getUser().getUserId());
					}
				} catch (Exception e) {
					bm.setUserName("<font color='red'>该用户被删除</font>");
					bm.setUserId(0);
				}

				VerifyLog log = verifyLogDao.findByType(borrow.getId(), "borrow", 1);
				if (log != null) {
					/*
					 * Date d = log.getTime(); //初审时间
					 * Calendar c = Calendar.getInstance();
					 * c.setTime(d);
					 * c.add(Calendar.DATE, borrow.getValidTime());
					 * Calendar now = Calendar.getInstance();
					 * now.setTime(DateUtil.getNow());
					 * bm.setFlow(c.before(now));
					 */
					bm.setStartTime(DateUtil.dateStr4(log.getTime()));
				}
				bm.setBorrowId(borrow.getId());
				bm.setUser(null);
				bm.setIps(model.getIps());
				bm.setCategory(borrow.getCategory());
				bm.setInvestCount(borrow.getInvestCount());
				bm.setAddIp(null);
				list.add(bm);
			}
		}
		pageDataList_.setList(list);
		return pageDataList_;
	}

	@Override
	public void cancel(Borrow item) throws Exception {
		long borrowId = item.getId();
		Borrow borrow = borrowDao.find(borrowId);
		if (null == borrow) {
			logger.error("该标已不存在于该系统中,borrowId:" + borrowId);
			throw new BorrowException("该标已不存在于该系统中,borrowId:" + borrowId, BorrowException.TYPE_JSON);
		}
		// 体验标撤回
		if (BorrowCategory.EXPERIENCE == borrow.getCategory()) {
			borrow.setStatus(BorrowStatus.STATUS_MANAGER_CANCEL2);
			borrowDao.update(borrow);
		} else {
			BorrowWorker worker = BorrowHelper.getWorker(borrow);
			worker.revokeBorrow();
			borrow.setRepaymentYesAccount(-borrow.getRepaymentYesAccount());
			borrow.setRepaymentYesInterest(-borrow.getRepaymentYesInterest());
			borrow.setStatus(BorrowStatus.STATUS_MANAGER_CANCEL);
			borrowDao.modifyBorrowAndRepay(borrow);

			autoBorrowService.autoCancel(borrow);
		}
		
	}

	@Override
	public void borrowCancel(Borrow borrow) throws Exception {
		if (borrow.getStatus() != 9) {
			throw new BorrowException("标状态异常，请刷新后操作", 1);
		}
		borrowDao.updateStatus(borrow.getId(), 5, 9);
	}

	/**
	 * 新浪代收 异步回调成功 还款逻辑执行
	 * 
	 * @param borrowRepayment
	 * @param
	 */
	@Override
	public void notifySuccessRepay(BorrowRepayment borrowRepayment) {
		List<BorrowCollection> borrowCollectionList = borrowCollectionDao.list(borrowRepayment.getBorrow().getId(),
				borrowRepayment.getPeriod());
		List<BondCollection> bondCollectionList = bondCollectionDao.getBondCollectionList(borrowRepayment.getId());

		Borrow borrow = borrowDao.find(borrowRepayment.getBorrow().getId());
		// 获取借款人账户信息
		Account account = accountDao.findByUserId(borrow.getUser().getUserId());
		BorrowWorker worker = BorrowHelper.getWorker(borrow);
		worker.validBeforeRepayment(borrowRepayment, account);
		// 设置web_status=1
		borrowRepayment.setWebStatus(1);
		borrowRepayment = borrowRepaymentDao.update(borrowRepayment);

		// 平台还款业务
		autoBorrowService.autoBorrowRepay(borrowRepayment);

		// 第三方还款业务
		tppInvestService.doTppRepay(borrowCollectionList, bondCollectionList);
	}

    /**
     * PS 还款
    * */
	@Override
	public void doRepay(BorrowRepayment borrowRepayment) {
		Borrow borrow = borrowDao.find(borrowRepayment.getBorrow().getId());
		String orderNo = OrderNoUtil.getInstance().getSerialNumber();
		String tppUserCustId = UserUtils.getUserTppCustId(borrow.getUser().getUserId());
		double transAmount = BigDecimalUtil.add(borrowRepayment.getCapital(), borrowRepayment.getInterest());
		Map<String, Object> map = new HashMap<String, Object>();
		long borrowId = borrow.getId();
		int period = borrowRepayment.getPeriod();
		double upRateSum = upRateCollectionDao.upRateCollectionSum(borrowId, period);
		double vipUpRateSum = userVipUprateCollectionDao.vipUpRateCollectionSum(borrowId, period);
		double upRateTotal = BigDecimalUtil.add(upRateSum, vipUpRateSum);
		map.put("upRateTotal", upRateTotal);
		map.put("transAmount", transAmount);

		// 把未还款状态更新为 还款中，如果可以更新 则可以还款，不能更新，直接抛错
		borrowRepaymentDao.updateStatus(BorrowRepaymentStatus.STATUS_REPAY_ING,
                BorrowRepaymentStatus.STATUS_WAIT_REPAY, borrowRepayment.getId());

		// TODO 下面的判断不精确 如果同时两个用户进来 都未读到还款的状态，就会出现多笔还款(同时点击会有问题)
		// List<TppTradeLog> list = tppTradeLogDao.find(borrowRepayment.getId(), SinaConstant.TRADE_SERVICE_REPAY,
		// SinaConstant.TRADE_CODE_1002);
		// if (list.size() > 0) {
		// logger.error("还款操作已受理，请耐心等待！");
		// throw new BorrowException("还款操作已受理，请耐心等待！",1);
		// }

		// 如果产生了加息收益，那么平台方需支付此笔金额
		if (upRateTotal > 0) {
			String upRateOrderNo = OrderNoUtil.getInstance().getSerialNumber();
			TppTradeLog tppTradeLogByUpRate = new TppTradeLog(SystemConfigHelper.getValue(Nid.MEMBER_EMAIL), null,
					SinaConstant.IDENTITY_TYPE_EMAIL, upRateTotal, 0, upRateOrderNo, SinaConstant.TRADE_STATUS_WAIT_PAY,
					SinaConstant.TRADE_CODE_1002, SinaConstant.TRADE_SERVICE_REPAY, borrowId, borrowRepayment.getId(),
					"", JSON.toJSONString(map));
			ConcurrentUtil.tppCollectTrade(tppTradeLogByUpRate);
			// tppTradeService.collTrade(tppTradeLog);
		}

		// 插入代收记录
		TppTradeLog tppTradeLog = new TppTradeLog(tppUserCustId, null, SinaConstant.IDENTITY_TYPE_UID, transAmount, 0,
				orderNo, SinaConstant.TRADE_STATUS_WAIT_PAY, SinaConstant.TRADE_CODE_1002,
				SinaConstant.TRADE_SERVICE_REPAY, borrowId, borrowRepayment.getId(), "", JSON.toJSONString(map));
		// tppTradeService.collTrade(tppTradeLog);
		ConcurrentUtil.tppCollectTrade(tppTradeLog);
		/*
		 * tppTradeLog.setAddTime(DateUtil.getNow());
		 * tppTradeLogDao.save(tppTradeLog);
		 * 
		 * TppModel tppModel = new TppModel();
		 * tppModel.setOrderId(orderNo);
		 * tppModel.setTppUserCustId(tppUserCustId);
		 * tppModel.setOut_trade_code(SinaConstant.TRADE_CODE_1002);
		 * tppModel.setSummary("用户还款");
		 * tppModel.setTppBorrowId(borrow.getId()+"");
		 * tppModel.setCan_repay_on_failed(SinaConstant.SINA_YES);
		 * tppModel.setMoney(transAmount);
		 * TppBaseInterface tppService = (TppBaseInterface) tppModel.tppServiceFactory();
		 * tppService.tppCollectTrade(tppModel);
		 */

		// tppInvestService.tppRepay(borrowRepayment);
		/*
		 * List<BorrowCollection> borrowCollectionList = borrowCollectionDao.list(borrowRepayment.getBorrow().getId(),
		 * borrowRepayment.getPeriod());
		 * List<BondCollection> bondCollectionList = bondCollectionDao.getBondCollectionList(borrowRepayment.getId());
		 * 
		 * Borrow borrow = borrowDao.find(borrowRepayment.getBorrow().getId());
		 * // 获取借款人账户信息
		 * Account account = accountDao.getAccountByUserId(borrow.getUser().getUserId());
		 * BorrowWorker worker = BorrowHelper.getWorker(borrow);
		 * worker.validBeforeRepayment(borrowRepayment, account);
		 * // 设置web_status=1
		 * borrowRepayment.setWebStatus(1);
		 * borrowRepayment = borrowRepaymentDao.update(borrowRepayment);
		 * 
		 * // 平台还款业务
		 * autoBorrowService.autoBorrowRepay(borrowRepayment);
		 * 
		 * // 第三方还款业务
		 * tppInvestService.doTppRepay(borrowCollectionList, bondCollectionList);
		 */
	}

	@Override
	public void doPriorRepay(BorrowRepayment borrowRepayment) {
		Borrow borrow = borrowRepayment.getBorrow();
		BorrowWorker worker = BorrowHelper.getWorker(borrow);
		if (worker.isLastPeriod(borrowRepayment.getPeriod())) {
			throw new BusinessException("你正在操作的提前还款为最后一期还款，不能进行提前还款操作！");
		}
		if ((borrowRepayment == null) || (borrowRepayment.getStatus() == BorrowRepaymentStatus.STATUS_YES_REPAY)
				|| (borrowRepayment.getWebStatus() == 1)) {
			throw new BorrowException("该期借款已经还款,请不要重复操作！", 1);
		}
		if ((borrow.getStatus() != 6) && (borrow.getStatus() != 7)) {
			throw new BorrowException("当前借款标的状态不能进行还款操作！", 1);
		}
		// 检查是否还有未还款的借款
		boolean hasAhead = borrowRepaymentDao.hasRepaymentAhead(borrowRepayment.getPeriod(),
				borrowRepayment.getBorrow().getId());
		if (hasAhead) {
			throw new BorrowException("还有尚未还款的借款！", 1);
		}
		// 设置webstatus=1
		borrowRepayment.setWebStatus(1);
		borrowRepayment = borrowRepaymentDao.update(borrowRepayment);
		User user = borrow.getUser();
		Account act = accountDao.findByUserId(user.getUserId());
		double waitRemainderRepayCapital = borrowRepaymentDao.getRemainderCapital(borrow.getId()); // 计算剩余待还本金
		double waitRemainderRepayInterest = borrowRepaymentDao.getwaitRpayInterest(borrow.getId(),
				borrowRepayment.getPeriod()); // 本次提前还款待还利息总和
		double waitRepayAccount = waitRemainderRepayCapital + waitRemainderRepayInterest;
		if (act.getUseMoney() < waitRepayAccount) {
			throw new BusinessException(
					"您账户的可用余额为：" + act.getUseMoney() + ",小于提前还款总额：" + waitRepayAccount + "，请充值再进行提前还款操作");
		}

		ConcurrentUtil.doPriorRepay(borrowRepayment);
	}

	@Override
	public Borrow find(long id) {
		return borrowDao.find(id);
	}

	@Override
	public Borrow find(String uuid) {
		return borrowDao.findObjByProperty("uuid", uuid);
	}

	@Override
	public void addBorrow(Borrow b) {
		borrowDao.update(b);
	}

	@Override
	public void verify(BorrowModel model, Operator operator) {
		Borrow borrow = borrowDao.find(model.getId());
		// borrow.setExpirationTime(DateUtil.rollDay(DateUtil.getNow(), borrow.getValidTime()));
		BorrowWorker worker = BorrowHelper.getWorker(borrow);
		int status = 0;
		Global.setTransfer("user", borrow.getUser());
		Global.setTransfer("borrow", borrow);
		if (model.getStatus() == 0) {
			status = -1;
			borrowDao.updateStatus(borrow.getId(), 2);
			if (borrow.getType() == BorrowType.TYPE_CREDIT) {
				UserCredit ua = userCreditDao.findObjByProperty("user.userId", borrow.getUser().getUserId());
				double amount = borrow.getAccount();
				userCreditDao.update(0, amount, -amount, borrow.getUser().getUserId());
				UserCreditLog amountLog = new UserCreditLog();
				amountLog.setUser(ua.getUser());
				amountLog.setAccount(amount);
				amountLog.setAccountAll(ua.getCredit());
				amountLog.setAccountUse(ua.getCreditUse() + amount);
				amountLog.setAccountNoUse(ua.getCreditNouse() - amount);
				amountLog.setType("credit");
				amountLog.setRemark("返还冻结信用额度");
				userCreditLogDao.save(amountLog);
			}
			// 发送消息通知
			AbstractExecuter executer = ExecuterHelper.getExecuter(BorrowVerifyFailNoticeExecuter.class);
			executer.execute(0, borrow.getUser());
		} else if (model.getStatus() == 1) {
			// 秒标初审通过 冻结解冻资金（利息和奖励）
			if (borrow.getType() == BorrowType.TYPE_SECOND) {
				worker.handleBorrowBeforePublish(borrow);
			}
			status = 1;
			borrowDao.updateStatus(borrow.getId(), 1, model.getPreStatus());
			borrowDao.updatefixedTime(borrow.getId(), model.getFixedTime());

			// 发送消息通知
			AbstractExecuter executer = ExecuterHelper.getExecuter(BorrowVerifySuccNoticeExecuter.class);
			executer.execute(0, borrow.getUser());
		}
		VerifyLog verifyLog = new VerifyLog(operator, "borrow", borrow.getId(), 1, status, model.getRemark());
		verifyLogDao.save(verifyLog);
	}

	@Override
	public void updateStatus(long id, int status, int preStatus) {
		borrowDao.updateStatus(id, status, preStatus);
	}

	@Override
	public Borrow getBorrowById(long id) {
		return borrowDao.find(id);
	}

	@Override
	public int trialCount(int status) {
		return borrowDao.trialCount(status);
	}

	@Override
	public int fullCount(int status) {
		return borrowDao.fullCount(status);
	}

	@Override
	public Object[] countByFinish() {
		return borrowDao.countByFinish();
	}

	@Override
	public void stopBorrow(Borrow borrow) {
		/* borrow.setScales(-1); */
		borrow.setIsTender(1);
		BorrowWorker worker = BorrowHelper.getWorker(borrow);
		worker.stopBorrow();
		worker.skipReview();
		borrowDao.update(worker.prototype());
		// 如果设置成跳过复审，就直接调用复审通过
		if (BorrowStatus.STATUS_RECHECK_PASS == borrow.getStatus()) {
			BorrowModel model = BorrowModel.instance(borrow);
			try {
				BorrowValueEvent event = new BorrowValueEvent();
				event.setBorrowModel(model);
				event.setTaskProcessorClass(VerifyFullSuccessTaskProcessor.class);
				QueueHandlers.put(event);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private QueryParam searchParam(QueryParam param, BorrowModel model) {
		// 利率
		if (model.getAprSearch() != -1) {
			switch (model.getAprSearch()) {
			case 1:
				param.addParam("apr", Operators.LTE, 6);
				break;
			case 2:
				param.addAddFilter("apr", Operators.GT, 6, "apr", Operators.LTE, 12);
				break;
			case 3:
				param.addAddFilter("apr", Operators.GT, 12, "apr", Operators.LTE, 18);
				break;
			case 4:
				param.addAddFilter("apr", Operators.GT, 18, "apr", Operators.LTE, 20);
				break;
			case 5:
				param.addParam("apr", Operators.GT, 20);
				break;
			default:
				break;
			}
		}
		// 金额
		if (model.getMoneySearch() != -1) {
			switch (model.getMoneySearch()) {
			case 2:
				param.addParam("account", Operators.LTE, 10000);
				break;
			case 3:
				param.addAddFilter("account", Operators.GT, 10000, "account", Operators.LTE, 50000);
				break;
			case 4:
				param.addAddFilter("account", Operators.GT, 50000, "account", Operators.LTE, 100000);
				break;
			case 5:
				param.addAddFilter("account", Operators.GT, 100000, "account", Operators.LTE, 200000);
				break;
			case 6:
				param.addAddFilter("account", Operators.GT, 200000, "account", Operators.LTE, 500000);
				break;
			case 7:
				param.addParam("account", Operators.GT, 500000);
				break;
			default:
				break;
			}
		}
		// 期限
		if (model.getTimeSearch() != -1) {
			switch (model.getTimeSearch()) {
			case 2:
				SearchFilter dayFilter = new SearchFilter("borrowTimeType", 1);
				SearchFilter monthFilter = new SearchFilter("timeLimit", Operators.LTE, 1);
				param.addOrFilter(dayFilter, monthFilter);
				break;
			case 3:
				param.addAddFilter("timeLimit", Operators.GT, 1, "timeLimit", Operators.LTE, 3);
				break;
			case 4:
				param.addAddFilter("timeLimit", Operators.GT, 3, "timeLimit", Operators.LTE, 6);
				break;
			case 5:
				param.addAddFilter("timeLimit", Operators.GT, 6, "timeLimit", Operators.LTE, 12);
				break;
			case 6:
				param.addParam("timeLimit", Operators.GT, 12);
				break;
			default:
				break;
			}
		}

		// 排序 1金额 2利率 3进度 4信用
		switch (model.getOrder()) {
		case -1:
			param.addOrder(OrderType.ASC, "account");
			break;
		case 1:
			param.addOrder(OrderType.DESC, "account");
			break;
		case -2:
			param.addOrder(OrderType.ASC, "apr");
			break;
		case 2:
			param.addOrder(OrderType.DESC, "apr");
			break;
		case -3:
			param.addOrder(OrderType.ASC, "scales");
			break;
		case 3:
			param.addOrder(OrderType.DESC, "scales");
			break;
		case -4:
			break;
		case 4:
			break;
		default:
			param.addOrder(OrderType.DESC, "id");
			break;
		}
		return param;
	}

	/**
	 * 校验用户是否借款人
	 *
	 */
	@Override
	public boolean isBorrowUser(long borrowId, long userId) {
		PageDataList<Borrow> borrowList = borrowDao
				.findAllPageList(QueryParam.getInstance().addParam("id", borrowId).addParam("user.userId", userId));
		boolean isBorrowUser = (borrowList != null) && (borrowList.getList() != null)
				&& (borrowList.getList().size() > 0);
		if (isBorrowUser) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public Borrow findNotFlow(long borrowId) {
		Borrow borrow = borrowDao.find(borrowId);
		try {
			if (borrow.getStatus() == 1) {
				borrow = borrowDao.findNotFlow(borrowId);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new BorrowException("当前借款标不存在或已流标");
		}
		return borrow;
	}

	@Override
	public boolean allowPublish(User user, BorrowModel model) {
		BorrowWorker worker = BorrowHelper.getWorker(model.prototype());
		boolean allowPublish;
		/* try { */
		allowPublish = worker.allowPublish(user);
		/*
		 * } catch (BusinessException e) {
		 * throw new BorrowException(e.getMessage());
		 * }
		 */
		return allowPublish;
	}

	@Override
	public void updateLoan(BorrowModel model, User user, Borrow oldBorrow, List<BorrowUpload> list,
			List<BorrowMortgage> borrowMortgageList, long[] delIds, long[] delMortgageIds) {
		BorrowWorker worker = BorrowHelper.getWorker(model.prototype());
		worker.checkModelData();
		worker.setBorrowField(user);
		Borrow b = worker.prototype();
		b.setVouchFirm(model.getVouchFirm());
		b.setId(oldBorrow.getId());
		if (borrowMortgageList != null) {
			borrowMortgageDao.save(borrowMortgageList);
		}
		if (delMortgageIds != null) {
			for (long id : delMortgageIds) {
				borrowMortgageDao.delete(id);
				List<BorrowUpload> bus = borrowUploadDao.findByMortgageId(id);
				for (BorrowUpload bu : bus) {
					borrowUploadDao.delete(bu.getId());
					String realPath = ServletActionContext.getServletContext().getRealPath(bu.getPicPath());
					new File(realPath).delete();
				}
			}
		}
		if (delIds != null) {
			for (long id : delIds) {
				BorrowUpload bu = borrowUploadDao.find(id);
				borrowUploadDao.delete(id);
				String realPath = ServletActionContext.getServletContext().getRealPath(bu.getPicPath());
				if (StringUtil.isNotBlank(realPath)) {
					new File(realPath).delete();
				}
			}
		}
		if (model.getType() == BorrowType.TYPE_CREDIT) {
			UserCredit userCredit = userCreditDao.findObjByProperty("user.userId", oldBorrow.getUser().getUserId());
			Borrow old = borrowDao.find(oldBorrow.getId());
			// 当前可用信用额度与当前标冻结金额总和
			double creditUse = BigDecimalUtil.add(userCredit.getCreditUse(), old.getAccount());
			if (model.getAccount() > creditUse) {
				throw new BorrowException("借款金额不能大于当前可用信用额度与当前标冻结信用额度总和", BusinessException.TYPE_JSON);
			}
			userCreditDao.update(0, old.getAccount(), -old.getAccount(), userCredit.getUser().getUserId());
			UserCreditLog backAmountLog = new UserCreditLog();
			backAmountLog.setUser(userCredit.getUser());
			backAmountLog.setType("credit_back");
			backAmountLog.setAccount(old.getAccount());
			backAmountLog.setAccountAll(userCredit.getCredit());
			backAmountLog.setAccountUse(creditUse);
			backAmountLog.setAccountNoUse(BigDecimalUtil.sub(userCredit.getCreditNouse(), old.getAccount()));
			backAmountLog.setRemark("退回信用额度");
			userCreditLogDao.save(backAmountLog);

			userCreditDao.update(0, -b.getAccount(), b.getAccount(), userCredit.getUser().getUserId());
			UserCreditLog amountLog = new UserCreditLog();
			amountLog.setUser(userCredit.getUser());
			amountLog.setType("credit_use");
			amountLog.setAccount(b.getAccount());
			amountLog.setAccountAll(userCredit.getCredit());
			amountLog.setAccountUse(BigDecimalUtil.add(userCredit.getCreditUse(), b.getAccount()));
			amountLog.setAccountNoUse(BigDecimalUtil.sub(userCredit.getCreditNouse(), b.getAccount()));
			amountLog.setRemark("使用信用额度");
			userCreditLogDao.save(amountLog);
		}

		borrowDao.update(b);

		/** 删除借款标缩略图 保证缩略图唯一 20150529 ctt start **/
		for (BorrowUpload bu : list) {
			if (bu.getType() == 6) {
				List<BorrowUpload> bList = borrowUploadDao.findByTypeAndBid(oldBorrow.getId(), 6);
				if (bList.size() > 0) {
					borrowUploadDao.delete(bList);
				}
			}
		}
		/** 删除借款标缩略图 保证缩略图唯一 20150529 ctt start **/
		borrowUploadDao.save(list);
	}

	@Override
	public void overduePayment(BorrowRepayment borrowRepayment) {
		Borrow borrow = borrowDao.find(borrowRepayment.getBorrow().getId());
		Account account = accountDao.findByUserId(borrow.getUser().getUserId());
		BorrowWorker worker = BorrowHelper.getWorker(borrow);
		worker.validBeforeRepayment(borrowRepayment, account);

		// // 把未还款状态更新为 还款中，如果可以更新 则可以还款，不能更新，直接抛错
		// // status=2 --> 9 webStatus --> 1
		// int result =
		// borrowRepaymentDao.updateOverdueStatus(borrowRepayment.getId(),BorrowRepayment.WEB_STATUS_NORMAL,BorrowRepayment.Status.STATUS_REPAY_ING.getValue(),
		// BorrowRepayment.Status.STATUS_INSTEAD_REPAY.getValue());
		// if(result != 1)
		// {
		// throw new BorrowException("已还款或还款中,请耐心等待!",BusinessException.TYPE_JSON);
		// }
		borrowRepayment.setWebStatus(1);
		borrowRepayment = borrowRepaymentDao.update(borrowRepayment);

		// 逾期垫付
		ConcurrentUtil.overduePayment(borrowRepayment);
	}

	@Override
	public List<BorrowUpload> findPicByBorrowId(long id) {
		QueryParam param = QueryParam.getInstance().addParam("borrow.id", id);
		return borrowUploadDao.findByCriteria(param);
	}

	@Override
	public List<BorrowModel> businessRepayment(User user) {
		QueryParam param = QueryParam.getInstance();
		param.addParam("user.userId", user.getUserId());
		SearchFilter filter1 = new SearchFilter("status", Operators.EQ, 6);
		SearchFilter filter2 = new SearchFilter("status", Operators.EQ, 7);
		param.addOrFilter(filter1, filter2);
		param.addOrder(OrderType.DESC, "addTime");
		List<Borrow> list = borrowDao.findByCriteria(param, 0, 4);
		List<BorrowModel> modelList = new ArrayList<BorrowModel>();
		for (Borrow item : list) {
			BorrowModel model = BorrowModel.instance(item);
			int currPeriod = borrowRepaymentDao.getCurrPeriod(item.getId());
			model.setCurrPeriod(currPeriod);
			modelList.add(model);
		}
		return modelList;
	}

	@Override
	public int findByStatusAndUserId(long userId, int status1, int status2) {
		return borrowDao.findByStatusAndUserId(userId, status1, status2);
	}

	@Override
	public double findAccountTotalByStatus(long userId, int status1, int status2) {
		return borrowDao.findAccountTotalByStatus(userId, status1, status2);
	}

	@Override
	public List<BorrowModel> investList(User user) {
		List<Borrow> itemList = borrowDao.getInvestList(user);
		List<BorrowModel> modelList = new ArrayList<BorrowModel>();
		if ((itemList != null) && (itemList.size() > 0)) {
			for (int i = 0; i < itemList.size(); i++) {
				Borrow borrow = itemList.get(i);
				BorrowModel bm = BorrowModel.instance(borrow);

				VerifyLog log = verifyLogDao.findByType(borrow.getId(), "borrow", 1);
				if (borrow.getPutStartTime() != null) {
					bm.setStartTime(DateUtil.dateStr4(borrow.getPutStartTime()));
				} else if ((log != null) && (log.getTime() != null)) {
					bm.setStartTime(DateUtil.dateStr4(log.getTime()));
				}

				modelList.add(bm);
			}
		}
		return modelList;
	}

	@Override
	public void updatePic(List<BorrowUpload> list, long[] delIds) {
		borrowUploadDao.save(list);
		if (delIds != null) {
			for (long id : delIds) {
				BorrowUpload bu = borrowUploadDao.find(id);
				borrowUploadDao.delete(id);
				String realPath = ServletActionContext.getServletContext().getRealPath(bu.getPicPath());
				new File(realPath).delete();
			}
		}
	}

	@Override
	public Double getBorrowAccountByDate(String date) {

		return borrowDao.getBorrowAccountByDate(date);
	}

	@Override
	public int count() {
		return borrowDao.count();
	}

	@Override
	public int getGuaranteeingCount(long userId) {
		return borrowDao.getGuaranteeingCount(userId);
	}

	@Override
	public double getGuaranteeingAccount(long userId) {
		return borrowDao.getGuaranteeingAccount(userId);
	}

	@Override
	public int getNeedGuaranteeRegisteCount(long userId) {
		return borrowDao.getNeedGuaranteeRegisteCount(userId);
	}

	@Override
	public double getNeedGuaranteeRegisteAccount(long userId) {
		return borrowDao.getNeedGuaranteeRegisteAccount(userId);
	}

	@Override
	public int getOverdueCount(long userId) {
		return borrowRepaymentDao.getOverdueCount(userId);
	}

	@Override
	public List<BorrowModel> getNeedGuaranteeRegisteList(long userId) {

		List<Borrow> itemList = borrowDao.getNeedGuaranteeRegisteList(userId);
		List<BorrowModel> modelList = new ArrayList<BorrowModel>();
		if ((itemList != null) && (itemList.size() > 0)) {
			for (Borrow borrow : itemList) {
				BorrowModel bm = BorrowModel.instance(borrow);
				try {
					bm.setUserName(borrow.getUser().getUserName());
					bm.setUserId(borrow.getUser().getUserId());
				} catch (Exception e) {
					bm.setUserName("");
					bm.setUserId(0);
				}
				bm.setUser(null);
				modelList.add(bm);
			}
		}
		return modelList;
	}

	@Override
	public PageDataList<BorrowModel> getGuaranteeingList(BorrowModel model) {
		QueryParam param = QueryParam.getInstance();
		param.addPage(model.getPage());
		// if (StringUtil.isNotBlank(model.getName())) {
		// param.addParam("name", Operators.LIKE, model.getName());
		// }HCB
		if (StringUtil.isNotBlank(model.getUserName())) {
			param.addParam("user.userName", Operators.LIKE, model.getUserName().trim());
		}
		if (model.getTime() == 7) {
			param.addParam("addTime", Operators.GT, DateUtil.rollDay(DateUtil.getNow(), -model.getTime()));
		} else if (model.getTime() != 0) {
			param.addParam("addTime", Operators.GT, DateUtil.rollMon(DateUtil.getNow(), -model.getTime()));
		}
		if (StringUtil.isNotBlank(model.getStartTime())) {
			Date startTime = DateUtil.valueOf(model.getStartTime() + " 00:00:00");
			param.addParam("addTime", Operators.GT, startTime);
		}
		if (StringUtil.isNotBlank(model.getEndTime())) {
			Date endTime = DateUtil.valueOf(model.getEndTime() + " 23:59:59");
			param.addParam("addTime", Operators.LT, endTime);
		}
		param.addParam("vouchFirm", model.getVouchFirm());
		param.addParam("guaranteeNo", Operators.NOTEQ, SearchFilter.EMPTY_AND_NULL); // 非空字符串和NULL
		param.addParam("guaranteeRate", Operators.GT, 0);
		SearchFilter orFilter1 = new SearchFilter("status", 1);
		SearchFilter orFilter2 = new SearchFilter("status", 3);
		SearchFilter orFilter3 = new SearchFilter("status", 6);
		SearchFilter orFilter4 = new SearchFilter("status", 7);
		param.addOrFilter(orFilter1, orFilter2, orFilter3, orFilter4);
		param.addOrder(OrderType.DESC, "id");
		PageDataList<Borrow> pageDataList = borrowDao.findPageList(param);
		PageDataList<BorrowModel> pageDataList_ = new PageDataList<BorrowModel>();
		List<BorrowModel> list = new ArrayList<BorrowModel>();
		pageDataList_.setPage(pageDataList.getPage());
		if (pageDataList.getList().size() > 0) {
			for (int i = 0; i < pageDataList.getList().size(); i++) {
				Borrow borrow = pageDataList.getList().get(i);
				BorrowModel borrowModel = BorrowModel.instance(borrow);
				borrowModel.setUserName(borrow.getUser().getUserName());
				borrowModel.setUser(null);
				list.add(borrowModel);
			}
		}
		pageDataList_.setList(list);
		return pageDataList_;
	}

	@Override
	public PageDataList<BorrowRepaymentModel> getOverdueGuaranteeList(BorrowModel model) {

		PageDataList<BorrowRepayment> pageDataList = borrowRepaymentDao.getOverdueGuaranteeList(model);
		PageDataList<BorrowRepaymentModel> pageDateList = new PageDataList<BorrowRepaymentModel>();
		List<BorrowRepaymentModel> list = new ArrayList<BorrowRepaymentModel>();
		pageDateList.setPage(pageDataList.getPage());
		if (pageDataList.getList().size() > 0) {
			for (int i = 0; i < pageDataList.getList().size(); i++) {
				BorrowRepayment r = pageDataList.getList().get(i);
				BorrowRepaymentModel rm = BorrowRepaymentModel.instance(r);
				Borrow borrow = r.getBorrow();
				User user = r.getUser();
				rm.setAccount(borrow.getAccount());
				rm.setApr(borrow.getApr());
				rm.setAddTime(borrow.getAddTime());
				rm.setBorrowId(borrow.getId());
				rm.setBorrowName(borrow.getName());
				rm.setUserName(user.getUserName());
				rm.setRealName(user.getRealName());
				rm.setMobilePhone(user.getMobilePhone());
				rm.setTimeLimit(borrow.getTimeLimit());
				rm.setType(borrow.getType());
				rm.setBorrowType(borrow.getType());
				rm.setBorrowTimeType(borrow.getBorrowTimeType());
				rm.setBorrowStyle(borrow.getStyle());
				rm.setBorrowStatus(borrow.getStatus());
				rm.setRepaymentAccount(BigDecimalUtil.add(r.getCapital(), r.getInterest(), r.getLateInterest()));
				rm.setBorrow(null);
				rm.setUser(null);
				list.add(rm);
			}
		}
		pageDateList.setList(list);
		return pageDateList;
	}

	@Override
	public PageDataList<BorrowRepaymentModel> getCompensatedList(BorrowModel model) {

		PageDataList<BorrowRepayment> pageDataList = borrowRepaymentDao.getCompensatedList(model);
		PageDataList<BorrowRepaymentModel> pageDateList = new PageDataList<BorrowRepaymentModel>();
		List<BorrowRepaymentModel> list = new ArrayList<BorrowRepaymentModel>();
		pageDateList.setPage(pageDataList.getPage());
		if (pageDataList.getList().size() > 0) {
			for (int i = 0; i < pageDataList.getList().size(); i++) {
				BorrowRepayment r = pageDataList.getList().get(i);
				BorrowRepaymentModel rm = BorrowRepaymentModel.instance(r);
				Borrow borrow = r.getBorrow();
				User user = r.getUser();

				rm.setAddTime(borrow.getAddTime());
				rm.setBorrowId(borrow.getId());
				rm.setBorrowName(borrow.getName());
				rm.setUserName(user.getUserName());
				rm.setRealName(user.getRealName());
				rm.setMobilePhone(user.getMobilePhone());
				rm.setTimeLimit(borrow.getTimeLimit());
				rm.setType(borrow.getType());
				rm.setBorrowStyle(borrow.getStyle()); // 设置还款方式
				rm.setAccount(borrow.getAccount());
				rm.setApr(borrow.getApr());
				rm.setBorrow(null);
				rm.setUser(null);
				list.add(rm);
			}
		}
		pageDateList.setList(list);
		return pageDateList;
	}

	@Override
	public void verifyBz(BorrowModel model, Operator operator) {
		Borrow borrow = borrowDao.find(model.getId());
		// borrow.setExpirationTime(DateUtil.rollDay(DateUtil.getNow(), borrow.getValidTime()));
		BorrowWorker worker = BorrowHelper.getWorker(borrow);
		int status = 0;
		Global.setTransfer("user", borrow.getUser());
		Global.setTransfer("borrow", borrow);
		if (model.getStatus() == 0) {
			status = -1;
			borrowDao.updateStatus(borrow.getId(), 2);
			if (borrow.getType() == BorrowType.TYPE_CREDIT) {
				UserCredit ua = userCreditDao.findObjByProperty("user.userId", borrow.getUser().getUserId());
				double amount = borrow.getAccount();
				userCreditDao.update(0, amount, -amount, borrow.getUser().getUserId());
				UserCreditLog amountLog = new UserCreditLog();
				amountLog.setUser(ua.getUser());
				amountLog.setAccount(amount);
				amountLog.setAccountAll(ua.getCredit());
				amountLog.setAccountUse(ua.getCreditUse() + amount);
				amountLog.setAccountNoUse(ua.getCreditNouse() - amount);
				amountLog.setType("credit");
				amountLog.setRemark("返还冻结信用额度");
				userCreditLogDao.save(amountLog);
			}
			// 发送消息通知
			AbstractExecuter executer = ExecuterHelper.getExecuter(BorrowVerifyFailNoticeExecuter.class);
			executer.execute(0, borrow.getUser());
		} else if (model.getStatus() == 1) {
			// 秒标初审通过 冻结解冻资金（利息和奖励）
			status = 1;
			worker.handleBorrowBeforePublish(borrow);
			AutoTenderConfRuleCheck autoTenderConf = RuleCheckHelper.getValue(AutoTenderConfRuleCheck.class);
			// 未设置定向密码且允许自动投标...
			if (autoTenderConf.enable_auto_tender.contains(borrow.getType()) && StringUtil.isBlank(borrow.getPwd())
					&& (borrow.getCategory().intValue() == 1) && ((borrow.getPutStartTime() == null)
							|| (borrow.getPutStartTime().getTime() <= DateUtil.getNow().getTime()))) {
				try {
					// 先将标状态改为19，标记为先处理自动投标
					borrowDao.updateStatus(borrow.getId(), 19, 0);
					BorrowModel borrowModel = BorrowModel.instance(borrow);
					borrowModel.setUserId(borrow.getUser().getUserId());
					ConcurrentUtil.autoTender(borrowModel);
				} catch (Exception e) {
					logger.error("触发disruptor自动投标异常");
				}
			} else {
				borrowDao.updateStatus(borrow.getId(), 1);
			}

			// 开启体验券投标
			if (model.getOpenExperience() == 1) {
				Global.getTransfer().put("borrow", borrow);
				Global.getTransfer().put("mostExperience", model.getMostExperience());
				Global.getTransfer().put("mostExperienceSingle", model.getMostExperienceSingle());
				logger.info("开启体验券投标， 借款标ID：" + borrow.getId());
				AbstractExecuter experienceVerifyExecuter = ExecuterHelper.getExecuter(ExperienceVerifyExecuter.class);
				experienceVerifyExecuter.execute(0, null);
			}

			// 发送消息通知
			AbstractExecuter executer = ExecuterHelper.getExecuter(BorrowVerifySuccNoticeExecuter.class);
			executer.execute(0, borrow.getUser());
		}
		VerifyLog verifyLog = new VerifyLog(operator, "borrow", borrow.getId(), 1, status, model.getRemark());
		verifyLogDao.save(verifyLog);
	}

	@Override
	public int getAllCount() {
		QueryParam param = QueryParam.getInstance();
		return borrowDao.countByCriteria(param);
	}

	@Override
	public double getAllMomeny() {
		return borrowDao.getAllMomeny();
	}

	@Override
	public int getAllOverduedCount() {
		return borrowDao.getAllOverduedCount();
	}

	@Override
	public int getCountByStatus(int status) {
		QueryParam param = QueryParam.getInstance();
		param.addParam("status", status);
		return borrowDao.countByCriteria(param);
	}

	@Override
	public double getMomenyByStatus(int status) {
		return borrowDao.getMomenyByStatus(status);
	}

	@Override
	public int getVerifyFullCount() {
		QueryParam param = QueryParam.getInstance();
		param.addParam("status", 1);
		param.addParam("scales", 100);
		return borrowDao.countByCriteria(param);
	}

	@Override
	public double getVerifyFullMomeny() {
		return borrowDao.getVerifyFullMomeny();
	}

	@Override
	public int getAllOverdueingCount() {
		return borrowDao.getAllOverdueingCount();
	}

	@Override
	public double getAllOverduedMomeny() {
		return borrowDao.getAllOverduedMomeny();
	}

	@Override
	public double getAllOverdueingMomeny() {
		return borrowDao.getAllOverdueingMomeny();
	}

	@Override
	public int getBorrowCountByDate(String date) {
		return borrowDao.getBorrowCountByDate(date);
	}

	@Override
	public double[] getDistributedByTypeAndDate(int type, String date) {
		double[] arr = new double[5];
		for (int i = 0; i < 5; i++) {
			arr[i] = borrowDao.getCountByTypeAndDate(type, i, date);
		}
		return arr;
	}

	@Override
	public double[] getProductDistributedByTypeAndDate(int type, String date) {
		List<BorrowConfig> list = borrowConfigDao.findAll();
		double[] arr = new double[list.size()];
		for (int i = 0; i < list.size(); i++) {
			arr[i] = borrowDao.getCountByTypeAndBorrowTypeAndDate(type, (int) list.get(i).getId(), date);
		}
		return arr;
	}

	@Override
	public double[] getDealCountByTypeAndBorrowTypeAndDate(int type, int borrowType, String date) {
		double[] result = new double[2];
		DateFormat sdf = new SimpleDateFormat("yyyy-MM");
		Date d;
		try {
			d = sdf.parse(date);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
		double count = borrowDao.getDealCountByTypeAndBorrowTypeAndDate(type, borrowType, date);
		result[0] = count;
		Date prevYear = DateUtil.rollYear(d, -1);
		String prevDate = DateUtil.dateStr(prevYear, "yyyy-MM");
		double prevCount = borrowDao.getDealCountByTypeAndBorrowTypeAndDate(type, borrowType, prevDate);
		double ratio = 0;
		if (prevCount != 0) {
			ratio = BigDecimalUtil.div(BigDecimalUtil.sub(count, prevCount), prevCount);
		}
		result[1] = ratio;
		return result;
	}

	@Override
	public double[] getDealRatiosByTypeAndDate(int type, String date) {
		double total = 0;
		List<BorrowConfig> list = borrowConfigDao.findAll();
		double[] arr = new double[list.size()];
		for (int i = 0; i < list.size(); i++) {
			arr[i] = borrowDao.getDealByTypeAndBorrowTypeAndDate(type, (int) list.get(i).getId(), date);
			total = BigDecimalUtil.add(total, arr[i]);
		}
		for (int i = 0; i < list.size(); i++) {
			double ratio = 0;
			if (total != 0) {
				ratio = BigDecimalUtil.div(arr[i], total);
			}
			arr[i] = ratio;
		}
		return arr;
	}

	@Override
	public double[][] getTurnoverByTypeAndDate(int type, String date) {
		int times = 0; // 循环次数
		if (date.isEmpty()) {
			times = 5;
		} else if (date.length() == 4) {
			times = 12;
		} else if (date.length() == 7) {
			DateFormat sdf = new SimpleDateFormat("yyyy-MM");
			Date d;
			try {
				d = sdf.parse(date);
			} catch (ParseException e) {
				throw new RuntimeException(e);
			}
			Calendar c = Calendar.getInstance();
			c.setTime(d);
			times = c.getActualMaximum(Calendar.DATE);
		} else if (date.length() == 10) {
			times = 24;
		}
		double[][] arr = new double[2][times];
		for (int i = 0; i < times; i++) {
			String dateTime;
			if (times == 5) {
				dateTime = ((Calendar.getInstance().get(Calendar.YEAR) - 4) + i) + "";
			} else {
				dateTime = date + (i > 8 ? "-" : "-0") + (i + 1);
			}
			arr[0][i] = borrowDao.getTurnoverByTypeAndDate(type, dateTime);
			if ((i > 0) && (arr[0][i - 1] != 0)) {
				arr[1][i] = BigDecimalUtil
						.round(BigDecimalUtil.div(BigDecimalUtil.sub(arr[0][i], arr[0][i - 1]), arr[0][i - 1]));
			}
		}
		return arr;
	}

	@Override
	public double[] getCumulativeBorrowByDate(String date) {
		int times = 0;
		if (date.isEmpty()) {
			times = 5;
		} else {
			times = 12;
		}
		double[] arr = new double[times];
		for (int i = 0; i < times; i++) {
			String dateTime;
			if (times == 5) {
				dateTime = ((Calendar.getInstance().get(Calendar.YEAR) - 4) + i) + "";
			} else {
				dateTime = date + (i > 8 ? "-" : "-0") + (i + 1);
			}
			arr[i] = borrowDao.getCumulativeBorrowByDate(dateTime);
		}
		return arr;
	}

	@Override
	public int[] getBorrowInfoByDate(String date) {
		int age1 = 0; // 年龄大于等于10小于20岁个数
		int age2 = 0; // 年龄大于等于20小于30岁个数
		int age3 = 0; // 年龄大于等于30小于40岁个数
		int age4 = 0; // 年龄大于等于40小于50岁个数
		int age5 = 0; // 年龄大于50岁个数
		int manCount = 0; // 男性个数
		int womanCount = 0; // 女性个数
		int[] arry = new int[19];
		List<String> cardIds = borrowDao.getBorrowCardIdsByDate(date);
		for (String cardId : cardIds) {
			String year = cardId.substring(6, 10);
			int currentYear = Calendar.getInstance().get(Calendar.YEAR);
			int age = currentYear - Integer.parseInt(year);
			if ((age >= 10) && (age < 20)) {
				age1++;
			} else if ((age >= 20) && (age < 30)) {
				age2++;
			} else if ((age >= 30) && (age < 40)) {
				age3++;
			} else if ((age >= 40) && (age < 50)) {
				age4++;
			} else if (age > 50) {
				age5++;
			}
			int length = cardId.length();
			char sexNum;
			if (length == 15) {
				sexNum = cardId.charAt(length - 1);
			} else {
				sexNum = cardId.charAt(length - 2);
			}
			// 获取性别 1:男,0:女
			int sex = sexNum % 2;
			if (sex == 0) {
				womanCount++;
			} else {
				manCount++;
			}
		}
		arry[0] = age1;
		arry[1] = age2;
		arry[2] = age3;
		arry[3] = age4;
		arry[4] = age5;
		arry[5] = womanCount;
		arry[6] = manCount;
		for (int i = 0; i < 8; i++) {
			arry[i + 7] = userInfoDao.getBorrowEducationsCountByDateAndEducation(date, i + 1);
		}
		for (int i = 0; i < 4; i++) {
			arry[i + 15] = userInfoDao.getBorrowMaritalStatusCountByDateAndMaritalStatus(date, i);
		}
		return arry;
	}

	@Override
	public Object[][] getBorrowAreaDistributedByDate(String date) {
		List<String> cardIds = borrowDao.getBorrowCardIdsByDate(date);
		Map<String, Integer> map = new HashMap<String, Integer>();
		for (String cardId : cardIds) {
			String province = IdcardUtils.getProvinceByIdCard(cardId);
			int count = 1;
			if (map.containsKey(province)) {
				count = map.get(province) + 1;
			}
			map.put(province, count);
		}
		Collection<Integer> coll = map.values();
		Set<String> set = map.keySet();
		Object[] provinces = set.toArray();
		Object[] counts = coll.toArray();
		Object[][] result = new Object[2][counts.length];
		result[0] = provinces;
		result[1] = counts;
		return result;
	}

	@Override
	public Borrow getLastBorrow() {
		return borrowDao.getLastBorrow();
	}

	@Override
	public boolean checkUserTenderList(long userId) {
		boolean flag = true;
		List<BorrowTender> itemList = borrowTenderDao.getTenderByUserId(userId);
		if ((itemList != null) && (itemList.size() > 0)) {
			for (BorrowTender borrowTender : itemList) {
				if ((borrowTender.getBorrow().getStatus() != 0) && (borrowTender.getBorrow().getStatus() != 1)
						&& (borrowTender.getBorrow().getStatus() != 3) && (borrowTender.getBorrow().getStatus() != 6)
						&& (borrowTender.getBorrow().getStatus() != 7)) {
				} else {
					flag = false;
				}
			}
		}
		return flag;
	}

	@Override
	public boolean checkUserBorrowList(long userId) {
		List<Borrow> itemList = borrowDao.getBorrowByUserId(userId);
		if ((itemList != null) && (itemList.size() > 0)) {
			for (Borrow borrow : itemList) {
				if ((borrow.getStatus() == BorrowStatus.STATUS_PUBLISHING) || (borrow.getStatus() == BorrowStatus.STATUS_TRIAL_PASSED) || (borrow.getStatus() == BorrowStatus.STATUS_RECHECK_PASS)
						|| (borrow.getStatus() == BorrowStatus.STATUS_REPAYMENT_START) || (borrow.getStatus() == BorrowStatus.STATUS_REPAYMENT_DOING)) {
                    return false;
				}
			}
		}
		return true;
	}

	@Override
	public long getTenderUserCountByBorrowid(long borrowId) {
		return borrowTenderDao.getTenderUserCountByBorrowid(borrowId);
	}

	@Override
	public Date getRepayTime(BorrowModel borrowModel, int period) {
		Date fullVerifyTime = DateUtil.getNow();
		Date reviewTime = borrowModel.getReviewTime();
		if (null != reviewTime) {
			fullVerifyTime = reviewTime;
		}
		Date repayDate = DateUtil.getLastSecIntegralTime(fullVerifyTime);
		int type = borrowModel.getType();
		if (BorrowType.TYPE_SECOND == type) {
			return repayDate;
		} else if (BorrowTimeType.DAY == borrowModel.getBorrowTimeType()) {
			repayDate = DateUtil.rollDay(repayDate, borrowModel.getTimeLimit());
			return repayDate;
		} else {
			int style = borrowModel.getStyle();
			if (BorrowStyle.STYLE_ONETIME_REPAYMENT == style) {// 一次性还款
				repayDate = DateUtil.rollMon(repayDate, borrowModel.getTimeLimit());
			} else if (BorrowStyle.STYLE_FULL_MONTHLY_INTEREST == style) {// 满标还息每月还息到期还本
				if (0 == period) {
					repayDate = DateUtil.rollMinute(DateUtil.getNow(), 5);// 5分钟后还款
				} else {
					repayDate = DateUtil.rollMon(repayDate, period);
				}
			} else {
				repayDate = DateUtil.rollMon(repayDate, period + 1);
			}
			return repayDate;
		}
	}

	@Override
	public Date getFlowRepayTime(BorrowModel borrowModel, int period) {
		Date fullVerifyTime = DateUtil.getNow();
		Date reviewTime = borrowModel.getReviewTime();
		if (null != reviewTime) {
			fullVerifyTime = reviewTime;
		}
		Date repayDate = DateUtil.getLastSecIntegralTime(fullVerifyTime);
		int type = borrowModel.getType();
		if (BorrowType.TYPE_SECOND == type) {
			return repayDate;
		} else if (BorrowTimeType.DAY == borrowModel.getBorrowTimeType()) {
			repayDate = DateUtil.rollDay(repayDate, borrowModel.getTimeLimit());
			return repayDate;
		} else {
			int style = borrowModel.getStyle();
			if (BorrowStyle.STYLE_ONETIME_REPAYMENT == style) {// 一次性还款
				repayDate = DateUtil.rollMon(repayDate, borrowModel.getTimeLimit());
			} else {
				repayDate = DateUtil.rollMon(repayDate, period + 1);
			}
			return repayDate;
		}
	}

	@Override
	public double getBorrowManageFeeRate(BorrowModel borrowModel) {
		double rate = 0.0;
		BorrowManageFeeRuleCheck borrowManageFeeRuleCheck = RuleCheckHelper.getValue(BorrowManageFeeRuleCheck.class);
		int timeLimit = borrowModel.getTimeLimit();
		int borrowTimeType = borrowModel.getBorrowTimeType();
		int calStyle = borrowManageFeeRuleCheck.cal_style;
		switch (calStyle) {
			case ManageFeeCalStyle.FIXED:
				BorrowConfig cfg = borrowConfigDao.find(new Long(borrowModel.getType()));
				if (null != cfg) {
					if (BorrowTimeType.DAY == borrowTimeType) {
						rate = BigDecimalUtil.div(BigDecimalUtil.mul(cfg.getDayManageFee(), timeLimit),
								3000);
					} else {
						rate = BigDecimalUtil.div(BigDecimalUtil.mul(cfg.getManageFee(), timeLimit), 100);
					}
				}
				break;
			case ManageFeeCalStyle.NOT_FIXED:
				if (BorrowTimeType.DAY == borrowTimeType
						|| (BorrowTimeType.MONTH == borrowTimeType && 1 == timeLimit)) {
					// 获得一个月的利率
					rate = DataUtils.toDouble(borrowManageFeeRuleCheck.monthRate.month_rate.get("1"));
				} else {
					// 获得多个月的利率
					rate = DataUtils.toDouble(borrowManageFeeRuleCheck.monthRate.month_rate.get(timeLimit + ""));
				}
				break;
			default:
				break;
		}
		return rate;
	}
}
